/*
* DebugProfiling.cpp
* iphone-gl-app
*
* Created by John Ryland on 16/06/09.
* Copyright 2009 InvertedLogic. All rights reserved.
*
*/
#include <stdlib.h>
#include <stdarg.h>
#include "String.h"
#include "DebugProfiling.h"
DebugProfiling::AutoEnter::AutoEnter(const char *f) : func(f)
{
}
DebugProfiling::AutoEnter::~AutoEnter()
{
}
DebugProfiling::AutoEnter DebugProfiling::enter(const char *func)
{
return DebugProfiling::AutoEnter(func);
}
#if 0
void *insideSampleList[10*60*1000];
void *totalSampleList[10*60*1000*5];
int insideSampleListPos = 0;
int totalSampleListPos = 0;
static void profilerSignalHandler(int signal, siginfo_t *, void *context)
{
if (signal != SIGPROF)
return;
/*
if (active_sampler_ == NULL) return;
TickSample sample;
// If profiling, we extract the current pc and sp.
if (active_sampler_->IsProfiling()) {
// Extracting the sample from the context is extremely machine dependent.
ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
mcontext_t& mcontext = ucontext->uc_mcontext;
#if __DARWIN_UNIX03
sample.pc = mcontext->__ss.__eip;
sample.sp = mcontext->__ss.__esp;
sample.fp = mcontext->__ss.__ebp;
#else // !__DARWIN_UNIX03
sample.pc = mcontext->ss.eip;
sample.sp = mcontext->ss.esp;
sample.fp = mcontext->ss.ebp;
#endif // __DARWIN_UNIX03
}
// We always sample the VM state.
sample.state = Logger::state();
active_sampler_->Tick(&sample);
*/
ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
mcontext_t& mcontext = ucontext->uc_mcontext;
insideSampleList[insideSampleListPos] = mcontext->ss.eip;
insideSampleListPos++;
}
DebugProfiling::DebugProfiling()
//: interval_(interval), profiling_(profiling), active_(false)
{
signal_handler_installed_ = false;
}
DebugProfiling::~DebugProfiling()
{
}
void DebugProfiling::start()
{
// There can only be one active sampler at the time on POSIX
// platforms.
if (active_sampler_ != NULL)
return;
// Request profiling signals.
struct sigaction sa;
sa.sa_sigaction = ProfilerSignalHandler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_SIGINFO;
if (sigaction(SIGPROF, &sa, &data_->old_signal_handler_) != 0)
return;
data_->signal_handler_installed_ = true;
// Set the itimer to generate a tick for each interval.
itimerval itimer;
itimer.it_interval.tv_sec = interval_ / 1000;
itimer.it_interval.tv_usec = (interval_ % 1000) * 1000;
itimer.it_value = itimer.it_interval;
setitimer(ITIMER_PROF, &itimer, &data_->old_timer_value_);
// Set this sampler as the active sampler.
active_sampler_ = this;
active_ = true;
}
void DebugProfiling::stop()
{
// Restore old signal handler
if (data_->signal_handler_installed_) {
setitimer(ITIMER_PROF, &data_->old_timer_value_, NULL);
sigaction(SIGPROF, &data_->old_signal_handler_, 0);
data_->signal_handler_installed_ = false;
}
// This sampler is no longer the active sampler.
active_sampler_ = NULL;
active_ = false;
}
#ifdef ENABLE_LOGGING_AND_PROFILING
static Sampler* active_sampler_ = NULL;
+static void
+SIG_HANDLER_SIGNATURE (sigprof_signal_handler)
+{
+ int pos;
+
+ GET_CONTEXT;
+
+ if (prof_counts >= MAX_PROF_SAMPLES)
+ return;
+ pos = InterlockedIncrement (&prof_counts);
+ prof_addresses [pos - 1] = mono_arch_ip_from_context (ctx);
+}
+
static void
SIG_HANDLER_SIGNATURE (sigquit_signal_handler)
{
@@ -8178,6 +8274,25 @@ mono_runtime_install_handlers (void)
#endif /* PLATFORM_WIN32 */
}
+static void
+setup_profiler (void)
+{
+ struct itimerval itval;
+ static int inited = 0;
+
+ /* about 10 minutes of samples */
+ prof_addresses = g_new0 (gpointer, MAX_PROF_SAMPLES);
+ itval.it_interval.tv_usec = 1000;
+ itval.it_interval.tv_sec = 0;
+ itval.it_value = itval.it_interval;
+ setitimer (ITIMER_PROF, &itval, NULL);
+ if (inited)
+ return;
+ inited = 1;
+ prof_table = g_hash_table_new (g_str_hash, g_str_equal);
+ add_signal_handler (SIGPROF, sigprof_signal_handler);
+}
+
#endif